package com.spa.application.service.member;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.spa.application.command.member.MassagistCollectionAddCommand;
import com.spa.application.dto.PageResult;
import com.spa.application.dto.member.*;
import com.spa.application.query.member.MemberMassagistCollectionQuery;
import com.spa.application.query.member.MemberMassagistDetailsQuery;
import com.spa.application.query.member.MemberMassagistQuery;
import com.spa.domain.entity.*;
import com.spa.domain.service.*;
import com.spa.infrastructure.common.KeyConstant;
import com.spa.infrastructure.enums.dict.massagist.MassagistStatusEnum;
import com.spa.infrastructure.enums.dict.order.OrderStatusEnum;
import com.spa.infrastructure.mapper.MassageServiceMapperStruct;
import com.spa.infrastructure.mapper.MassagistMapperStruct;
import com.spa.infrastructure.repository.condition.*;
import com.spa.infrastructure.repository.service.SysConfigurationRepositoryService;
import com.spa.infrastructure.util.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
@Data
public class MemberMassagistApplicationService {

    @Resource
    private UserInfoService userInfoService;
    @Resource
    private MassagistService massagistService;

    @Resource
    //服务
    private MassageService massageService;

    @Resource
    private OrderService orderInfoSercie;

    @Resource
    private AddressService addressSercie;

    @Autowired
    private MassagistEvaluateService massagistEvaluateService;

    @Autowired
    private SysConfigurationRepositoryService sysConfigurationRepositoryService;

    /**
     * 获取技师分页
     *
     * @author: lig
     * @date: 2023/12/6
     */
    public PageResult<MemberMassagistDTO> page(MemberMassagistQuery query) {
        MassagistCondition condition = MassagistMapperStruct.INSTANCE.query2Condition(query);
        if (ObjectUtils.isNotEmpty(query) && StringUtils.isNotNull(query.getMassagistName())) {
            condition.setName(query.getMassagistName());
        }
        Page<Massagist> page = massagistService.massagistPage(condition);
        PageResult<MemberMassagistDTO> memberMassagistDTOPageResult = MassagistMapperStruct.INSTANCE.entity2MemberDto4Page(page);
        memberMassagistDTOPageResult.getRecords().forEach(memberMassagistDTO -> {
            if (!Objects.equals(memberMassagistDTO.getStatus(), MassagistStatusEnum.$10.getCode())) {
                double queryLon = Convert.toDouble(query.getLon(), 0d);
                double queryLat = Convert.toDouble(query.getLat(), 0d);
                double massagistLon = Convert.toDouble(memberMassagistDTO.getLon(), 0d);
                double massagistLat = Convert.toDouble(memberMassagistDTO.getLat(), 0d);
                memberMassagistDTO.setDistance(PositionUtil.getDistance(queryLon, queryLat, massagistLon, massagistLat).toString());
            }
            OrderInfoCondition orderInfoCondition = new OrderInfoCondition();
            orderInfoCondition.setMassagistId(memberMassagistDTO.getId());
            memberMassagistDTO.setSelectCount(orderInfoSercie.countByCondition(orderInfoCondition));
            //距离
            memberMassagistDTO.setDistance(OrderUtils.buildDistance(memberMassagistDTO.getDistance()));
            //获取技师列表
            List<Massagist> massagistList = massagistService.list(Lists.newArrayList(memberMassagistDTO.getId()));
            massagistList.forEach(m -> {
                List<Date> dates = getDates(m.getId());
                memberMassagistDTO.setAppointmentTime(OrderUtils.toDate(OrderUtils.getEarliestAvailableAppointmentTime(dates)));
            });
        });
        //排序处理
        if (CollUtil.isNotEmpty(memberMassagistDTOPageResult.getRecords())) {
            //状态服务中和可预约的   距离升序
            List<MemberMassagistDTO> sort1List = memberMassagistDTOPageResult.getRecords().stream().filter(a -> Objects.equals(a.getStatus(), MassagistStatusEnum.$20.getCode()) || a.getStatus() == MassagistStatusEnum.$30.getCode())
                    .sorted(Comparator.comparing(MemberMassagistDTO::getDistance)).toList();
            //休息中的   距离升序
            List<MemberMassagistDTO> sort2List = memberMassagistDTOPageResult.getRecords().stream().filter(a -> Objects.equals(a.getStatus(), MassagistStatusEnum.$10.getCode()))
                    .sorted(Comparator.comparing(MemberMassagistDTO::getDistance)).toList();
            List<MemberMassagistDTO> sortList = new ArrayList<>();
            if (CollUtil.isNotEmpty(sort1List)) sortList.addAll(sort1List);
            if (CollUtil.isNotEmpty(sort2List)) sortList.addAll(sort2List);
            memberMassagistDTOPageResult.setRecords(sortList);
        }
        return memberMassagistDTOPageResult;
    }

    /**
     * 通过技师id 获取 已经被预约的时间
     *
     * @param massagistId 技师id
     * @return 已经被预约的时间的集合
     */
    public List<Date> getDates(Long massagistId) {
        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //第二天的23：30：00   变更 24：00：00
        String towTime = LocalDateTime.now().plusDays(1).withHour(23).withMinute(30).withSecond(00).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //现在到明天的现在的技师订单
        OrderInfoCondition condition = new OrderInfoCondition();
        condition.setMassagistId(massagistId);
        condition.setBeginAppointTime(nowTime);
        condition.setEndAppointTime(towTime);
        condition.setStatusList(Lists.newArrayList(OrderStatusEnum.$20.getCode(), OrderStatusEnum.$30.getCode()));
        List<OrderInfo> orderInfos = orderInfoSercie.orderList(condition);
        return orderInfos.stream().map(OrderInfo::getAppointTime).toList();
    }

    /**
     * 通过技师id 获取 已经被预约的时间
     *
     * @param ids 技师id集合
     * @return 已经被预约的时间的集合
     */
    public Map<Long, List<Date>> getDatesByMassagists(List<Long> ids) {
        String nowTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //第二天的23：30：00   变更 24：00：00
        String towTime = LocalDateTime.now().plusDays(1).withHour(23).withMinute(30).withSecond(00).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        //现在到明天的现在的技师订单
        OrderInfoCondition condition = new OrderInfoCondition();
        condition.setMassgistIds(ids);
        condition.setBeginAppointTime(nowTime);
        condition.setEndAppointTime(towTime);
        condition.setStatusList(Lists.newArrayList(OrderStatusEnum.$20.getCode(), OrderStatusEnum.$30.getCode()));
        List<OrderInfo> orderInfos = orderInfoSercie.orderList(condition);
        return orderInfos.stream().collect(Collectors.groupingBy(OrderInfo::getMassagistId, Collectors.mapping(OrderInfo::getAppointTime, Collectors.toList())));
    }

    /**
     * 获取 我的 技师收藏 分页列表
     *
     * @author: lig
     * @date: 2024-01-10
     */
    public PageResult<MemberMassagistDTO> pageMyMassagistCollection(MemberMassagistCollectionQuery query) {

        Long userId = SessionUtil.getUser().getExtUserId();
        Assert.isTrue(ObjectUtils.isNotEmpty(userId), "登录后可查看我的收藏");

        //获取用户收藏
        List<Long> mIdList = massagistService.collectionMassagitsByUserId(userId);
        if (CollUtil.isNotEmpty(mIdList)) {
            MassagistCondition massagistCondition = MassagistMapperStruct.INSTANCE.queryMassagistCollection2Condition(query);
            massagistCondition.setMassagistIds(mIdList);

            PageResult<MemberMassagistDTO> pageResult = MassagistMapperStruct.INSTANCE.entity2MemberDto4Page(massagistService.massagistPage(massagistCondition));
            pageResult.getRecords().forEach(a -> {

                a.setDistance(buildDistance(query.getLon(), query.getLat(), a.getLon(), a.getLat()));
                a.setSelectCount(buildSelectCount(a.getId()) + a.getSelectCount());

                //获取技师列表
                List<Massagist> massagistList = massagistService.list(Lists.newArrayList(a.getId()));
                massagistList.forEach(m -> {
                    List<Date> dates = getDates(m.getId());
                    LocalDateTime localDateTime = OrderUtils.getEarliestAvailableAppointmentTime(dates);
                    a.setAppointmentTime(OrderUtils.toDate(localDateTime));
                    LocalDateTime localDateTime1 = OrderUtils.getLeisureEarliestAvailableAppointmentTime(LocalDateTime.now());
                    a.setTag(DateUtil.isEq(localDateTime1, localDateTime) ? "可服务" : "可预约");
                    a.setSubStatus(DateUtil.isEq(localDateTime1, localDateTime) ? 10 : 20);
                });
            });

            return pageResult;
        }
        return new PageResult<>();

    }


    /**
     * 技师收藏
     *
     * @author: lig
     * @date: 2024-01-10
     */
    public MemberCollectionDTO collection(MassagistCollectionAddCommand command) {

        MemberCollectionDTO dto = new MemberCollectionDTO();
        dto.setCollection(false);

        UserCollectionRefCondition condition = new UserCollectionRefCondition();
        condition.setUserId(SessionUtil.getUser().getExtUserId());
        condition.setMassagistId(command.getMassagistId());
        if (userInfoService.getUserCollection(SessionUtil.getUser().getExtUserId(), command.getMassagistId())) {
            userInfoService.cancelUserCollection(SessionUtil.getUser().getExtUserId(), command.getMassagistId());
        } else {
            if (userInfoService.userCollection(SessionUtil.getUser().getExtUserId(), command.getMassagistId())) {
                dto.setCollection(true);
            }
        }

        return dto;
    }


    /**
     * 获取技师全部
     *
     * @author: lig
     * @date: 2023/12/6
     */
    public PageResult<MemberMassagistDTO> memberAllList(MemberMassagistQuery query) {
        MassagistCondition condition = MassagistMapperStruct.INSTANCE.query2Condition(query);
        if (ObjectUtils.isNotEmpty(query) && StringUtils.isNotNull(query.getMassagistName())) {
            condition.setName(query.getMassagistName());
        }
        List<Massagist> list = massagistService.memberList(condition);
        list = list.stream().filter(massagist -> !sysConfigurationRepositoryService.getValueByKey(KeyConstant.MASSAGIST_BLACKLIST).contains(String.valueOf(massagist.getId()))).toList();
        PageResult<MemberMassagistDTO> pageResult = new PageResult<>();
        pageResult.setTotal(0L);
        pageResult.setSize(query.getSize());
        pageResult.setCurrent(query.getCurrent());
        //有城市id查询
        if (ObjectUtils.isNotEmpty(list)) {
            List<MemberMassagistDTO> listDto = MassagistMapperStruct.INSTANCE.entity2MemberDto4List(list);
            buildMemberMassagistDTO(listDto, query);
            //技师状态为可预约和服务中
            List<MemberMassagistDTO> list1Dto = listDto.stream().filter(f -> f.getStatus().equals(MassagistStatusEnum.$20.getCode())
                    || f.getStatus().equals(MassagistStatusEnum.$30.getCode())).toList();
            //技师状态为休息中
            List<MemberMassagistDTO> list2Dto = listDto.stream().filter(f -> Objects.equals(f.getStatus(), MassagistStatusEnum.$10.getCode())).toList();
            //dto1距离升序
            List<MemberMassagistDTO> sort1List = list1Dto.stream().sorted(Comparator.comparingDouble(o -> Convert.toDouble(o.getDistance()))).toList();
            //dto2距离升序
            List<MemberMassagistDTO> sort2List = list2Dto.stream().sorted(Comparator.comparingDouble(o -> Convert.toDouble(o.getDistance()))).toList();
            List<MemberMassagistDTO> sortList = new ArrayList<>();
            if (CollUtil.isNotEmpty(sort1List)) sortList.addAll(sort1List);
            if (CollUtil.isNotEmpty(sort2List)) sortList.addAll(sort2List);
            pageResult.setTotal(Convert.toLong(list.size()));
            pageResult.setRecords(sortList);
            return pageResult;
        }
        pageResult.setRecords(new ArrayList<>());
        return pageResult;
    }

    /**
     * 构造距离
     *
     * @author: lig
     * @date: 2024-01-13
     */
    private String buildDistance(String lon1, String lat1, String lon2, String lat2) {
        //距离
        double queryLon = Convert.toDouble(lon1, 0d);
        double queryLat = Convert.toDouble(lat1, 0d);
        double massagistLon = Convert.toDouble(lon2, 0d);
        double massagistLat = Convert.toDouble(lat2, 0d);
        double tempNum = PositionUtil.getDistance(queryLon, queryLat, massagistLon, massagistLat);
        if (tempNum < 0) {
            return "0";
        }
        return Convert.toStr(tempNum, "0");
    }

    /**
     * 构造选择人数
     *
     * @author: lig
     * @date: 2024-01-13
     */
    private Long buildSelectCount(Long massagistId) {
        OrderInfoCondition orderInfoCondition = new OrderInfoCondition();
        orderInfoCondition.setMassagistId(massagistId);
        return Convert.toLong(orderInfoSercie.countByCondition(orderInfoCondition), 0L);

    }

    private List<MemberMassagistDetailsCarouselDTO> buildCarousel(String lifePhoto) {
        List<MemberMassagistDetailsCarouselDTO> carouselList = new ArrayList<>();
        List<String> convertKeyList = (List<String>) Convert.toList(lifePhoto);
        if (CollUtil.isNotEmpty(convertKeyList)) {
            convertKeyList.forEach(a -> {
                MemberMassagistDetailsCarouselDTO carouselDTO = new MemberMassagistDetailsCarouselDTO();
                carouselDTO.setUrl(a);
                carouselList.add(carouselDTO);
            });
        }
        return carouselList;
    }


    /**
     * 获取 用户端 技师详情 重构
     *
     * @author: lig
     * @date: 2024-01-13
     */
    public MemberMassagistDetailsDTO memberDetails(MemberMassagistDetailsQuery query) {
        Massagist mass = massagistService.infoById(Convert.toLong(query.getMassagistId()));
        MemberMassagistDetailsDTO dto = MassagistMapperStruct.INSTANCE.entity2MemberDto(mass);
        if (BeanUtil.isEmpty(dto)) return null;
        dto.setDist(buildDistance(mass.getLon(), mass.getLat(), query.getLon(), query.getLat()));
        //多少人选择
        dto.setSelectCount(buildSelectCount(dto.getId()) + dto.getSelectCount());
        dto.setWorkPhoto(mass.getWorkPhoto());
        //技师轮播
        dto.setCarousel(buildCarousel(mass.getLifePhoto()));
        MassageServiceCondition conditionService = new MassageServiceCondition();
        conditionService.setMassagistId(dto.getId());
        //获取技师相关服务
        Page<MassageServiceEntity> serviceEntityPage = massageService.servicePageList(conditionService);
        if (serviceEntityPage != null && CollUtil.isNotEmpty(serviceEntityPage.getRecords())) {
            List<MemberServiceDTO> serviceDtoList = MassageServiceMapperStruct.INSTANCE.entity2MemberDto4List(serviceEntityPage.getRecords());
            dto.setServiceList(serviceDtoList);
        } else {
            dto.setServiceList(new ArrayList<>());
        }
        //add 用户收藏相关 lig 2024-01-13
        List<Long> umcIdList = userInfoService.myUserCollectionIds();
        //用户是否收藏  add 用户收藏相关 lig 2024-01-10
        if (umcIdList.stream().anyMatch(umc -> umc.equals(dto.getId()))) {
            dto.setUserCollectionFlag(true);
        }
        return dto;
    }


    /**
     * 构造 dto数据
     *
     * @author: lig
     * @date: 2024/1/25
     */
    private void buildMemberMassagistDTO(List<MemberMassagistDTO> listDto, MemberMassagistQuery query) {
        List<Long> ids = listDto.stream().map(MemberMassagistDTO::getId).toList();
        Map<Long, List<Date>> map = getDatesByMassagists(ids);
        List<Map<String, Object>> mapList = orderInfoSercie.countByMassagistIds(ids);
        Map<String, Object> longIntegerMap = new HashMap<>();
        mapList.forEach(longIntegerMap::putAll);
        mapList.forEach(l -> longIntegerMap.put(l.get("massagist_id").toString(), l.get("count")));
        listDto.forEach(a -> {
            long selectCount = Convert.toLong(longIntegerMap.get(String.valueOf(a.getId())), 0L);
            a.setDistance(buildDistance(query.getLon(), query.getLat(), a.getLon(), a.getLat()));
            a.setSelectCount(selectCount + a.getSelectCount());
            LocalDateTime localDateTime = OrderUtils.getEarliestAvailableAppointmentTime(map.getOrDefault(a.getId(), new ArrayList<>()));
            a.setAppointmentTime(OrderUtils.toDate(localDateTime));
            LocalDateTime localDateTime1 = OrderUtils.getLeisureEarliestAvailableAppointmentTime(LocalDateTime.now());
            a.setTag(DateUtil.isEq(localDateTime1, localDateTime) ? "可服务" : "可预约");
            a.setSubStatus(DateUtil.isEq(localDateTime1, localDateTime) ? 10 : 20);
            List<String> photos = new ArrayList<>();
            photos.add(a.getWorkPhoto());
            if (ObjectUtils.isNotEmpty(a.getLifePhoto())) {
                photos.addAll(Arrays.stream(a.getLifePhoto().split(",")).toList());
            }
            a.setWorkPhotoAndLifePhoto(photos);
        });
    }

}
